package net.xdclass.component;

import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.*;
import lombok.extern.slf4j.Slf4j;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * MinIO 文件存储引擎实现类，基于 AmazonS3Client 实现对象存储相关功能
 *
 * @author 姜阿木
 * @date 2025/5/6 17:34
 */
@Component
@Slf4j
public class MinIoFileStoreEngine implements StoreEngine {

    @Resource
    private AmazonS3Client amazonS3Client;

    /**
     * 判断指定的 Bucket 是否存在
     *
     * @param bucketName Bucket 名称
     * @return 是否存在
     */
    @Override
    public boolean bucketExists(String bucketName) {
        if (bucketName == null || bucketName.isEmpty()) {
            log.warn("Bucket name is null or empty");
            return false;
        }
        return amazonS3Client.doesBucketExistV2(bucketName);
    }

    /**
     * 删除指定的 Bucket，若 Bucket 不为空则删除失败
     *
     * @param bucketName Bucket 名称
     * @return 删除是否成功
     */
    @Override
    public boolean removeBucket(String bucketName) {
        if (bucketName == null || bucketName.isEmpty()) {
            log.warn("Bucket name is null or empty");
            return false;
        }
        try {
            if (!bucketExists(bucketName)) {
                log.info("Bucket name: {} does not exist", bucketName);
                return false;
            }

            List<S3ObjectSummary> objects = listObjects(bucketName);
            if (objects != null && !objects.isEmpty()) {
                log.warn("Bucket name: {} is not empty, cannot delete", bucketName);
                return false;
            }

            amazonS3Client.deleteBucket(bucketName);
            boolean exists = bucketExists(bucketName);
            if (exists) {
                log.error("Failed to delete bucket: {}", bucketName);
                return false;
            }
            log.info("Bucket name: {} deleted successfully", bucketName);
            return true;
        } catch (Exception e) {
            log.error("Error deleting bucket: {}", bucketName, e);
            return false;
        }
    }

    /**
     * 创建新的 Bucket
     *
     * @param bucketName Bucket 名称
     */
    @Override
    public void createBucket(String bucketName) {
        if (bucketName == null || bucketName.isEmpty()) {
            log.warn("Bucket name is null or empty");
            return;
        }
        try {
            if (bucketExists(bucketName)) {
                log.info("Bucket name: {} already exists", bucketName);
                return;
            }
            amazonS3Client.createBucket(bucketName);
            log.info("Bucket name: {} created successfully", bucketName);
        } catch (Exception e) {
            log.error("Error creating bucket: {}", bucketName, e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取所有 Bucket 列表
     *
     * @return Bucket 列表
     */
    @Override
    public List<Bucket> getAllBucket() {
        try {
            return amazonS3Client.listBuckets();
        } catch (Exception e) {
            log.error("Error fetching all buckets", e);
            return List.of();
        }
    }

    /**
     * 列出指定 Bucket 下的所有对象摘要
     *
     * @param bucketName Bucket 名称
     * @return 对象摘要列表
     */
    @Override
    public List<S3ObjectSummary> listObjects(String bucketName) {
        if (bucketName == null || bucketName.isEmpty()) {
            log.warn("Bucket name is null or empty");
            return List.of();
        }
        if (!bucketExists(bucketName)) {
            return List.of();
        }
        try {
            return amazonS3Client.listObjects(bucketName).getObjectSummaries();
        } catch (Exception e) {
            log.error("Error listing objects in bucket: {}", bucketName, e);
            return List.of();
        }
    }

    /**
     * 判断指定对象是否存在
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @return 是否存在
     */
    @Override
    public boolean doesObjectExist(String bucketName, String objectKey) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty()) {
            log.warn("Bucket name or objectKey is null or empty");
            return false;
        }
        if (!bucketExists(bucketName)) {
            return false;
        }
        return amazonS3Client.doesObjectExist(bucketName, objectKey);
    }

    /**
     * 上传本地文件到指定 Bucket
     *
     * @param bucketName     Bucket 名称
     * @param objectKey      对象 Key
     * @param localFileName  本地文件路径
     * @return 上传是否成功
     */
    @Override
    public boolean upload(String bucketName, String objectKey, String localFileName) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty() || localFileName == null || localFileName.isEmpty()) {
            log.warn("Invalid parameters for upload");
            return false;
        }
        if (!bucketExists(bucketName)) {
            log.warn("Bucket does not exist: {}", bucketName);
            return false;
        }
        try {
            amazonS3Client.putObject(bucketName, objectKey, new File(localFileName));
            log.info("File uploaded to bucket: {}, key: {}", bucketName, objectKey);
            return true;
        } catch (Exception e) {
            log.error("Error uploading file to bucket: {}, key: {}", bucketName, objectKey, e);
            return false;
        }
    }

    /**
     * 上传 MultipartFile 到指定 Bucket
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @param file       MultipartFile 文件
     * @return 上传是否成功
     */
    @Override
    public boolean upload(String bucketName, String objectKey, MultipartFile file) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty() || file == null) {
            log.warn("Invalid parameters for multipart upload");
            return false;
        }
        if (!bucketExists(bucketName)) {
            log.warn("Bucket does not exist: {}", bucketName);
            return false;
        }
        try {
            ObjectMetadata metadata = new ObjectMetadata();
            metadata.setContentType(file.getContentType());
            metadata.setContentLength(file.getSize());
            amazonS3Client.putObject(bucketName, objectKey, file.getInputStream(), metadata);
            log.info("Multipart file uploaded to bucket: {}, key: {}", bucketName, objectKey);
            return true;
        } catch (Exception e) {
            log.error("Error uploading multipart file to bucket: {}, key: {}", bucketName, objectKey, e);
            return false;
        }
    }

    /**
     * 删除指定对象
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @return 删除是否成功
     */
    @Override
    public boolean delete(String bucketName, String objectKey) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty()) {
            log.warn("Invalid parameters for delete");
            return false;
        }
        if (!bucketExists(bucketName)) {
            return false;
        }
        try {
            amazonS3Client.deleteObject(bucketName, objectKey);
            boolean exists = doesObjectExist(bucketName, objectKey);
            if (exists) {
                log.error("Failed to delete object: {}/{}", bucketName, objectKey);
                return false;
            }
            log.info("Object deleted from bucket: {}, key: {}", bucketName, objectKey);
            return true;
        } catch (Exception e) {
            log.error("Error deleting object: {}/{}", bucketName, objectKey, e);
            return false;
        }
    }

    /**
     * 获取对象的预签名下载链接
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @param timeout    超时时间
     * @param unit       时间单位
     * @return 下载链接
     */
    @Override
    public String getDownloadUrl(String bucketName, String objectKey, long timeout, TimeUnit unit) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty()) {
            log.warn("Invalid parameters for generating download URL");
            return null;
        }
        if (!bucketExists(bucketName)) {
            return null;
        }
        try {
            Date expiration = new Date(System.currentTimeMillis() + unit.toMillis(timeout));
            String url = amazonS3Client.generatePresignedUrl(bucketName, objectKey, expiration).toString();
            log.info("Generated download URL for object: {}/{}", bucketName, objectKey);
            return url;
        } catch (Exception e) {
            log.error("Error generating download URL for object: {}/{}", bucketName, objectKey, e);
            return null;
        }
    }

    /**
     * 将对象内容写入 HttpServletResponse，用于浏览器下载
     *
     * @param bucketName Bucket 名称
     * @param objectKey  对象 Key
     * @param response   HTTP 响应对象
     */
    @Override
    public void download2Response(String bucketName, String objectKey, HttpServletResponse response) {
        if (bucketName == null || bucketName.isEmpty() || objectKey == null || objectKey.isEmpty()) {
            log.warn("Invalid parameters for download");
            return;
        }
        if (!bucketExists(bucketName)) {
            log.warn("Bucket does not exist: {}", bucketName);
            return;
        }
        try (S3Object s3Object = amazonS3Client.getObject(bucketName, objectKey)) {
            String fileName = extractFileName(objectKey);
            response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
            response.setContentType("application/force-download");
            response.setCharacterEncoding("UTF-8");

            IOUtils.copy(s3Object.getObjectContent(), response.getOutputStream());
            log.info("File downloaded from bucket: {}, key: {}", bucketName, objectKey);
        } catch (IOException e) {
            log.error("Error downloading file from bucket: {}, key: {}", bucketName, objectKey, e);
        }
    }


    @Override
    public PartListing listMultipart(String bucketName, String objectKey, String uploadId) {
        try {
            ListPartsRequest request = new ListPartsRequest(bucketName, objectKey, uploadId);
            return amazonS3Client.listParts(request);
        } catch (Exception e) {
            log.error("errorMsg={}", e);
            return null;
        }
    }

    @Override
    public InitiateMultipartUploadResult initMultipartUploadTask(String bucketName, String objectKey, ObjectMetadata metadata) {
        try {
            InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectKey, metadata);
            return amazonS3Client.initiateMultipartUpload(request);
        } catch (Exception e) {
            log.error("errorMsg={}", e);
            return null;
        }
    }


    @Override
    public URL genePreSignedUrl(String bucketName, String objectKey, HttpMethod httpMethod, Date expiration, Map<String, Object> params) {
        try {
            GeneratePresignedUrlRequest genePreSignedUrlReq =
                    new GeneratePresignedUrlRequest(bucketName, objectKey, httpMethod)
                            .withExpiration(expiration);
            //遍历params作为参数加到genePreSignedUrlReq里面，比如 添加上传ID和分片编号作为请求参数
            //genePreSignedUrlReq.addRequestParameter("uploadId", uploadId);
            //genePreSignedUrlReq.addRequestParameter("partNumber", String.valueOf(i));
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                genePreSignedUrlReq.addRequestParameter(entry.getKey(), String.valueOf(entry.getValue()));
            }
            // 生成并获取预签名URL
            return amazonS3Client.generatePresignedUrl(genePreSignedUrlReq);
        } catch (Exception e) {
            log.error("errorMsg={}", e);
            return null;
        }
    }

    @Override
    public CompleteMultipartUploadResult mergeChunks(String bucketName, String objectKey, String uploadId, List<PartETag> partETags) {
        CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(bucketName, objectKey, uploadId, partETags);
        return amazonS3Client.completeMultipartUpload(request);

    }

    /**
     * 提取文件名，防止路径问题
     */
    private String extractFileName(String objectKey) {
        int lastSlashIndex = objectKey.lastIndexOf('/');
        if (lastSlashIndex >= 0 && lastSlashIndex < objectKey.length() - 1) {
            return objectKey.substring(lastSlashIndex + 1);
        }
        return objectKey;
    }
}
